﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using itau.im.dado;
using itau.im.entidade;
using EnterpriseLibraryWrapper;
using System.Data;
using System.Data.OleDb;

namespace itau.im.negocio
{
    public class ImportadorArquivoVertices : IImportadorArquivoVertices
    {
        public const int SIM = 1;
        public const string NOME_CAMPO_DATABASE = "Data Base";
        public const string NOME_CAMPO_PRAZO = "Prazo";
        public const string NOME_CAMPO_VALOR = "Valor";

        public IList<CurvaExecucaoPonto> ImportarVertices(ImportacaoArquivo importArquivo, RegistroExecucaoCurva registroExecucaoCurva)
        {
            IList<CurvaExecucaoPonto> listaVertices = new List<CurvaExecucaoPonto>();

            switch (importArquivo.Sigla.ToUpper())
            {
                case "TXT":
                case "CSV":
                    listaVertices = LerArquivoTXTCSV(importArquivo, registroExecucaoCurva);
                    break;

                case "XLS":
                    listaVertices = LerArquivoXLS(importArquivo, registroExecucaoCurva);
                    break;
                case "XLSX":
                    listaVertices = LerArquivoXLSX(importArquivo, registroExecucaoCurva);
                    break;
            }

            return listaVertices;
        }

        private IList<CurvaExecucaoPonto> LerArquivoTXTCSV(ImportacaoArquivo importArquivo, RegistroExecucaoCurva registroExecucaoCurva)
        {
            StreamReader stream = null;
            CurvaExecucaoPonto curvaExecucaoPonto = null;
            IList<CurvaExecucaoPonto> listaVertices = new List<CurvaExecucaoPonto>();

            try
            {

                stream = new StreamReader(string.Format("{0}\\{1}", importArquivo.Diretorio, importArquivo.NomeArquivo));

                string linha = null;
                string[] linhaSeparada = null;
                Int32 contLinha = 0;

                while ((linha = stream.ReadLine()) != null)
                {
                    if (contLinha > 0)
                    {
                        curvaExecucaoPonto = new CurvaExecucaoPonto();
                        linhaSeparada = linha.Split(';');

                        curvaExecucaoPonto.CodigoCurva = registroExecucaoCurva.CodigoCurva;
                        curvaExecucaoPonto.DataHoraExecucaoCurva = registroExecucaoCurva.DataHoraExecucaoCurva;
                        curvaExecucaoPonto.DataInclusaoVigencia = registroExecucaoCurva.DataInclusaoVigencia;
                        curvaExecucaoPonto.DataVencimento = registroExecucaoCurva.DataHoraExecucaoCurva.Date.AddDays(Int32.Parse(linhaSeparada[0]));
                        curvaExecucaoPonto.ValorVertice = double.Parse(linhaSeparada[1]);
                        curvaExecucaoPonto.IndicadorVertice = SIM;
                        curvaExecucaoPonto.QuantidadeDiasCorridos = Int32.Parse(linhaSeparada[0]);

                        listaVertices.Add(curvaExecucaoPonto);
                    }

                    contLinha += 1;
                }

                stream.Close();

                CalendarioReguaBS calendarioRegua = new CalendarioReguaBS(registroExecucaoCurva.DataHoraExecucaoCurva, curvaExecucaoPonto.DataVencimento.AddDays(1));

                foreach (CurvaExecucaoPonto curvaExecucao in listaVertices)
                {
                    var linhaArquivo = calendarioRegua.Regua[curvaExecucao.DataVencimento.ToString("yyyyMMdd")];
                    curvaExecucao.QuantidadeDiasUteis = linhaArquivo.DiasUteis;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                stream.Dispose();
                curvaExecucaoPonto = null;
                stream = null;
            }

            return listaVertices;
        }

        private IList<CurvaExecucaoPonto> LerArquivoXLS(ImportacaoArquivo importArquivo, RegistroExecucaoCurva registroExecucaoCurva)
        {
            string cnnString = String.Format(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=""Excel 8.0;HDR=YES;""", string.Format("{0}\\{1}", importArquivo.Diretorio, importArquivo.NomeArquivo));
            return LerArquivoXLS(importArquivo, registroExecucaoCurva, cnnString);
        }

        private IList<CurvaExecucaoPonto> LerArquivoXLSX(ImportacaoArquivo importArquivo, RegistroExecucaoCurva registroExecucaoCurva)
        {
            string cnnString = String.Format(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=""Excel 12.0;HDR=YES;""", string.Format("{0}\\{1}", importArquivo.Diretorio, importArquivo.NomeArquivo));
            return LerArquivoXLS(importArquivo, registroExecucaoCurva, cnnString);
        }

        private IList<CurvaExecucaoPonto> LerArquivoXLS(ImportacaoArquivo importArquivo, RegistroExecucaoCurva registroExecucaoCurva, string conexaoArquivo)
        {
            IList<CurvaExecucaoPonto> listaVertices = new List<CurvaExecucaoPonto>();
            CurvaExecucaoPonto curvaExecucaoPonto = null;

            string cnnString = String.Format(conexaoArquivo, string.Format("{0}\\{1}", importArquivo.Diretorio, importArquivo.NomeArquivo));
            string isql = "SELECT " + NOME_CAMPO_PRAZO + ", " + NOME_CAMPO_VALOR + " FROM [{0}$]";
            System.Data.OleDb.OleDbConnection cnn = new System.Data.OleDb.OleDbConnection(cnnString);
            System.Data.OleDb.OleDbDataAdapter da = new System.Data.OleDb.OleDbDataAdapter(String.Format(isql, importArquivo.NomePlanilha), cnn);
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();

            try
            {
                da.Fill(ds);
                dt = ds.Tables[0];

                if (dt.Rows.Count > 0)
                {
                    //Garantir que a linha obtida possua valor de Prazo, para montar a regua.
                    double ultimoValorPrazo = 0;

                    for (int cont = dt.Rows.Count - 1; cont >= 0; cont--)
                    {
                        if (dt.Rows[cont][NOME_CAMPO_PRAZO].ToString().Trim() != "")
                        {
                            ultimoValorPrazo = Int32.Parse(dt.Rows[cont][NOME_CAMPO_PRAZO].ToString());
                            break;
                        }
                    }

                    CalendarioReguaBS calendarioRegua = new CalendarioReguaBS(registroExecucaoCurva.DataHoraExecucaoCurva,
                                            registroExecucaoCurva.DataHoraExecucaoCurva.Date.AddDays(ultimoValorPrazo + 1));

                    for (int cont = 0; cont < dt.Rows.Count; cont++)
                    {
                        if (dt.Rows[cont][NOME_CAMPO_VALOR].ToString() != null && dt.Rows[cont][NOME_CAMPO_VALOR].ToString() != ""
                            && dt.Rows[cont][NOME_CAMPO_PRAZO].ToString() != null && dt.Rows[cont][NOME_CAMPO_PRAZO].ToString() != "")
                        {
                            curvaExecucaoPonto = new CurvaExecucaoPonto();

                            curvaExecucaoPonto.CodigoCurva = registroExecucaoCurva.CodigoCurva;
                            curvaExecucaoPonto.DataHoraExecucaoCurva = registroExecucaoCurva.DataHoraExecucaoCurva;
                            curvaExecucaoPonto.DataInclusaoVigencia = registroExecucaoCurva.DataInclusaoVigencia;
                            curvaExecucaoPonto.IndicadorVertice = SIM;
                            curvaExecucaoPonto.ValorVertice = double.Parse(dt.Rows[cont][NOME_CAMPO_VALOR].ToString());
                            curvaExecucaoPonto.QuantidadeDiasCorridos = Int32.Parse(dt.Rows[cont][NOME_CAMPO_PRAZO].ToString());
                            curvaExecucaoPonto.DataVencimento = registroExecucaoCurva.DataHoraExecucaoCurva.Date.AddDays(Int32.Parse(dt.Rows[cont]["Prazo"].ToString()));
                            var linha = calendarioRegua.Regua[curvaExecucaoPonto.DataVencimento.ToString("yyyyMMdd")];
                            curvaExecucaoPonto.QuantidadeDiasUteis = linha.DiasUteis;
                            listaVertices.Add(curvaExecucaoPonto);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cnn.Close();
                cnn.Dispose();
                da.Dispose();
                cnn = null;
                da = null;
                ds = null;
            }

            return listaVertices;
        }

        public void RenomearArquivo(ImportacaoArquivo importArquivo, string nomeArquivo)
        {
            string diretorio;
            string nomeAntigo;

            try
            {
                diretorio = importArquivo.Diretorio;
                nomeAntigo = importArquivo.NomeArquivo;

                File.Move(
                    diretorio + @"\" + nomeAntigo,
                    diretorio + @"\" + nomeArquivo);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public DateTime LerDataBaseArquivo(ImportacaoArquivo importArquivo)
        {
            DateTime dataBase = DateTime.MinValue;
            string cnnString;

            switch (importArquivo.Sigla.ToUpper())
            {
                case "XLS":
                    cnnString = String.Format(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=""Excel 8.0;HDR=YES;""", string.Format("{0}\\{1}", importArquivo.Diretorio, importArquivo.NomeArquivo));
                    dataBase = LerDataBaseXLS(importArquivo, cnnString);

                    break;
                case "XLSX":
                    cnnString = String.Format(@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=""Excel 12.0;HDR=YES;""", string.Format("{0}\\{1}", importArquivo.Diretorio, importArquivo.NomeArquivo));
                    dataBase = LerDataBaseXLS(importArquivo, cnnString);

                    break;
                case "TXT":
                case "CSV":
                    dataBase = LerDataBaseTXTCSV(importArquivo);
                    break;
                default:

                    break;
            }

            return dataBase;
        }

        private DateTime LerDataBaseXLS(ImportacaoArquivo importArquivo, string conexaoArquivo)
        {
            DateTime dataBase = DateTime.MinValue;

            string cnnString = String.Format(conexaoArquivo, string.Format("{0}\\{1}", importArquivo.Diretorio, importArquivo.NomeArquivo));
            string isql = "SELECT [" + NOME_CAMPO_DATABASE + "] FROM [{0}$]";
            OleDbConnection cnn = new OleDbConnection(cnnString);
            OleDbDataAdapter da = new OleDbDataAdapter(String.Format(isql, importArquivo.NomePlanilha), cnn);
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();

            try
            {
                da.Fill(ds);
                dt = ds.Tables[0];

                if (dt.Rows.Count > 0)
                {
                    if (dt.Rows[0].ItemArray.Count() > 0)
                    {
                        DateTime.TryParse(dt.Rows[0].ItemArray[0].ToString(), out dataBase);
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                cnn.Close();
                cnn.Dispose();
                da.Dispose();
                cnn = null;
                da = null;
                ds = null;
            }

            return dataBase;
        }

        private DateTime LerDataBaseTXTCSV(ImportacaoArquivo importArquivo)
        {
            DateTime dataBase = DateTime.MinValue;

            StreamReader stream = null;

            try
            {
                stream = new StreamReader(string.Format("{0}\\{1}", importArquivo.Diretorio, importArquivo.NomeArquivo));

                string linha = null;
                string[] linhaSeparada = null;
                int indexColunaDataBase = int.MinValue;

                while (!stream.EndOfStream || dataBase != DateTime.MinValue)
                {
                    linha = stream.ReadLine();
                    if (linha == null)
                    {
                        break;
                    }
                    else
                    {
                        linhaSeparada = linha.Split(';');

                        //Verifica se o índice da coluna data base já foi encontrada
                        if (indexColunaDataBase == int.MinValue)
                        {
                            //Verifica se a linha possui o cabeçalho da data base
                            if (linhaSeparada.Count(p => p.ToUpper().Contains(NOME_CAMPO_DATABASE.ToUpper())) > 0)
                            {
                                indexColunaDataBase = 0;

                                //Busca o índice da coluna em que está a data base
                                while (!linhaSeparada[indexColunaDataBase].Trim().ToUpper().Contains(NOME_CAMPO_DATABASE.ToUpper()))
                                {
                                    indexColunaDataBase++;
                                }
                            }
                        }
                        else
                        {
                            //Tenta converter cada linha da coluna data base até encontrar uma conversão válida
                            DateTime.TryParse(linhaSeparada[indexColunaDataBase], out dataBase);
                        }
                    }
                    
                }

                stream.Close();

                return dataBase;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                stream.Dispose();
                stream = null;
            }
        }
    }
}

